package cn.tannn.surenessdemo.controller;

import cn.jdevelops.annotation.mapping.PathRestController;
import cn.jdevelops.entity.basics.vo.SerializableVO;
import cn.jdevelops.exception.annotation.DisposeException;
import cn.jdevelops.result.result.ResultVO;
import cn.tannn.surenessdemo.constant.RoleConstant;
import cn.tannn.surenessdemo.controller.dto.AddAuthRoleDTO;
import cn.tannn.surenessdemo.controller.vo.AuthRoleVO;
import cn.tannn.surenessdemo.controller.vo.AuthRouteVO;
import cn.tannn.surenessdemo.controller.vo.ResourceVO;
import cn.tannn.surenessdemo.user.entity.AuthResource;
import cn.tannn.surenessdemo.user.entity.AuthRole;
import cn.tannn.surenessdemo.user.entity.AuthRoute;
import cn.tannn.surenessdemo.user.service.AuthRouteService;
import cn.tannn.surenessdemo.user.service.RoleService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;
import java.util.Optional;

/**
 * 角色管理
 * 1. 查询角色
 * 2. 路由授权（资源授权）
 *  2.1 权限力度到路由时，使用路由授权
 *      2.1.1 查询路由（已拥有和未拥有的list
 *  2.2 权限力度到接口时，使用资源赋权
 *      2.2.1 查询接口（已拥有和未拥有的list
 * 3. 关联用户
 * 4. 停启用角色
 * 5. 新增角色
 * 6. 删除角色（初始化角色不能被删除
 *
 * @author tnnn
 * @version V1.0
 * @date 2022-07-19 12:57
 */
@PathRestController("role")
@Slf4j
@Api(tags = "角色管理", value = "系统权限")
@RequiredArgsConstructor
@ApiSupport(order =4)
public class RoleController {

    private final RoleService roleService;
    private final AuthRouteService authRouteService;




    @ApiOperation(value = "新增角色", notes = "角色管理")
    @PostMapping("addRole")
    @ApiOperationSupport(order = 1)
    public ResultVO<String> addRole(@RequestBody @Validated AddAuthRoleDTO authRole) {
        if(RoleConstant.NO_REGIST_ROLE.contains(authRole.getName())||
                RoleConstant.NO_REGIST_ROLE.contains(authRole.getCode())){
            return ResultVO.fail("非法注册角色");
        }
        if (roleService.addRole(authRole)) {
            if (log.isDebugEnabled()) {
                log.debug("add role success: {}", authRole);
            }
            return ResultVO.success();
        } else {
            return ResultVO.fail("角色已存在");
        }
    }


    @ApiOperation(value = "删除角色", notes = "角色管理(删除角色,角色-用户,角色-资源)")
    @GetMapping("/deleteRole")
    @ApiOperationSupport(order = 2)
    public ResultVO<String> deleteRole(@NotBlank String roleCode) {
        if (roleService.deleteRole(roleCode)) {
            if (log.isDebugEnabled()) {
                log.debug("delete role success: {}", roleCode);
            }
            return ResultVO.success();
        } else {
            log.debug("delete role fail: {}", roleCode);
            return ResultVO.fail("删除角色失败，此处无此角色");
        }
    }

    @ApiOperation(value = "查询所有角色", notes = "角色管理")
    @GetMapping("findAll")
    @ApiOperationSupport(order = 4)
    public ResultVO<List<AuthRoleVO>> findAll(){
        Optional<List<AuthRole>> allRole = roleService.getAllRole();
        return allRole.map(roles -> ResultVO.successForData(SerializableVO.to(roles, AuthRoleVO.class))).orElseGet(() -> ResultVO.fail("暂无角色"));
    }


    @ApiOperation(value = "角色新增资源", notes = "角色管理")
    @PostMapping("/authority/resource/add")
    @ApiOperationSupport(order = 5)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleCode",value = "角色code",type = "String",paramType = "query"),
            @ApiImplicitParam(name = "resourceCode",value = "资源code",type = "String",paramType = "query"),
    })
    @DisposeException(messages = "当前角色已经拥有此资源，请勿重复设置",exceptions = SQLIntegrityConstraintViolationException.class)
    public ResultVO<String> authorityRoleResource(@RequestParam @NotBlank String roleCode,
                                                  @RequestParam @NotBlank String resourceCode) {
        roleService.authorityRoleResource(roleCode,resourceCode);
        return ResultVO.success();
    }



    @ApiOperation(value = "角色删除资源", notes = "角色管理")
    @PostMapping("/authority/resource/delete")
    @ApiOperationSupport(order = 6)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleCode",value = "角色code",type = "String",paramType = "query"),
            @ApiImplicitParam(name = "resourceCode",value = "资源code",type = "String",paramType = "query"),
    })
    public ResultVO<String> deleteAuthorityRoleResource(@RequestParam @NotBlank String roleCode,
                                                        @RequestParam @NotBlank String resourceCode) {
        roleService.deleteAuthorityRoleResource(roleCode,resourceCode);
        return ResultVO.success();
    }

    @ApiOperation(value = "角色新增路由", notes = "角色管理")
    @PostMapping("/authority/route/add")
    @ApiOperationSupport(order = 5)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleCode",value = "角色code",type = "String",paramType = "query"),
            @ApiImplicitParam(name = "routeCode",value = "路由code",type = "String",paramType = "query"),
    })
    @DisposeException(messages = "当前角色已经拥有此路由，请勿重复设置",exceptions = SQLIntegrityConstraintViolationException.class)
    public ResultVO<String> authorityRoleRoute(@RequestParam @NotBlank String roleCode,
                                               @RequestParam @NotBlank String routeCode) {
        roleService.authorityRoleRoute(roleCode,routeCode);
        return ResultVO.success();
    }


    @ApiOperation(value = "角色删除资源", notes = "角色管理")
    @PostMapping("/authority/route/delete")
    @ApiOperationSupport(order = 6)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleCode",value = "角色code",type = "String",paramType = "query"),
            @ApiImplicitParam(name = "routeCode",value = "路由code",type = "String",paramType = "query"),
    })
    public ResultVO<String> deleteAuthorityRoleRoute(@RequestParam @NotBlank String roleCode,
                                                        @RequestParam @NotBlank String routeCode) {
        roleService.deleteAuthorityRoleRoute(roleCode,routeCode);
        return ResultVO.success();
    }

    @ApiOperation(value = "查询角色拥有的资源", notes = "角色管理")
    @GetMapping("/resource/own")
    @ApiOperationSupport(order = 7)
    public ResultVO<List<ResourceVO>> getResourceOwnByRole(@NotBlank String roleCode) {
        List<AuthResource> resourcePage = roleService.getResourceOwnRole(roleCode);
        return ResultVO.success(SerializableVO.to(resourcePage,ResourceVO.class),"拥有"+resourcePage.size()+"个资源");
    }


    @ApiOperation(value = "获取角色拥有的路由", notes = "角色管理")
    @GetMapping("/routeOwnRole")
    @ApiOperationSupport(order = 11)
    public ResultVO<List<AuthRouteVO>> routeOwnRole(@RequestParam @NotBlank String resourceCode) {
        List<AuthRoute> routeOwnRole = authRouteService.getRouteOwnRole(resourceCode);
        return ResultVO.successForData(SerializableVO.to(routeOwnRole, AuthRouteVO.class));
    }


    @ApiOperation(value = "启用角色", notes = "角色管理")
    @PostMapping("enable")
    @ApiOperationSupport(order = 9)
    public ResultVO<String> enable(@RequestBody @NotEmpty List<String> roleCodes){
        roleService.enable(roleCodes);
        return ResultVO.success();
    }

    @ApiOperation(value = "禁用角色", notes = "角色管理")
    @PostMapping("disabled")
    @ApiOperationSupport(order = 10)
    public ResultVO<String> disabled(@RequestBody @NotEmpty List<String> roleCodes){
        roleService.disabled(roleCodes);
        return ResultVO.success();
    }



}
